#!/usr/bin/env python3

import os
import sys
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.font_manager as fm
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
from sklearn.cluster import KMeans, DBSCAN
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
import argparse
import glob
from datetime import datetime
import pickle
import json
import warnings
from scipy.spatial.distance import cdist

# 添加当前目录到路径，便于导入其他模块
current_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(current_dir)

# 简化字体处理逻辑
# 1. 尝试使用相对路径加载字体
# 2. 如果失败，使用系统默认字体并确保中文正确显示
try:
    # 尝试几种可能的路径
    font_paths = [
        os.path.join(current_dir, '../../font/SimHei.otf'),  # 相对路径
        os.path.join(current_dir, '../../../font/SimHei.otf'), 
        '/home/xixi/SAGIN/ns-allinone-3.42/ns-3.42/scratch/SimChannelAlloc-SAGINIoV/font/SimHei.otf'  # 绝对路径
    ]
    
    font_loaded = False
    for font_path in font_paths:
        if os.path.exists(font_path):
            # 配置中文字体
            plt.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体
            plt.rcParams['axes.unicode_minus'] = False    # 解决保存图像负号'-'显示为方块的问题
            chinese_font = fm.FontProperties(fname=font_path)
            font_loaded = True
            print(f"成功加载字体: {font_path}")
            break
    
    if not font_loaded:
        # 使用系统默认字体
        chinese_font = None
        print("未能找到SimHei字体文件，将使用系统默认字体")
        # 尝试使用其他一些可能的中文字体
        plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'WenQuanYi Micro Hei', 'Microsoft YaHei', 'SimSun', 'sans-serif']
        plt.rcParams['axes.unicode_minus'] = False

except Exception as e:
    chinese_font = None
    print(f"配置字体时出错: {str(e)}，将使用系统默认字体")
    plt.rcParams['font.sans-serif'] = ['DejaVu Sans', 'sans-serif']
    plt.rcParams['axes.unicode_minus'] = False

# 隐藏字体相关的警告消息
import logging
logging.getLogger('matplotlib.font_manager').setLevel(logging.ERROR)

class SAGINPreprocessor:
    """SAGIN(空天地一体化网络)预处理器，用于分析车辆数据并确定最佳基站和卫星位置"""
    
    def __init__(self, vehicle_data_path, output_dir=None, 
                 num_ground_stations=10, num_satellites=5, cluster_method='kmeans'):
        """
        初始化预处理器
        
        参数:
            vehicle_data_path (str): 车辆数据CSV文件的完整路径
            output_dir (str): 输出目录
            num_ground_stations (int): 地面基站数量
            num_satellites (int): 卫星数量
            cluster_method (str): 聚类方法，默认为KMeans
        """
        self.vehicle_data_path = vehicle_data_path
        
        # 从文件路径提取文件夹名称作为输出目录的一部分
        folder_name = os.path.basename(os.path.dirname(vehicle_data_path))
        
        if output_dir is None:
            output_dir = os.path.join(current_dir, 'output', folder_name)
            
        self.output_dir = output_dir
        
        # 创建子文件夹以组织输出
        self.viz_dir = os.path.join(self.output_dir, 'visualizations')  # 所有可视化图形
        self.data_dir = os.path.join(self.output_dir, 'data')  # 数据文件 (CSV, JSON)
        self.position_dir = os.path.join(self.output_dir, 'positions')  # 基站和卫星位置
        self.analysis_dir = os.path.join(self.output_dir, 'analysis')  # 分析结果
        
        # 确保所有输出目录都存在
        for directory in [self.output_dir, self.viz_dir, self.data_dir, self.position_dir, self.analysis_dir]:
            os.makedirs(directory, exist_ok=True)
            
        self.num_ground_stations = num_ground_stations
        self.num_satellites = num_satellites
        self.cluster_method = cluster_method
        
        # 使用全局字体对象
        self.chinese_font = chinese_font
        
        # 存储处理后的数据
        self.vehicle_data = None
        self.vehicle_ids = []
        self.vehicle_trajectories = []
        self.ground_stations = None
        self.satellites = None
        
        # 日志文件
        self.log_file = os.path.join(self.output_dir, f"process_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt")
        
        # 初始化日志
        with open(self.log_file, 'w') as f:
            f.write(f"SAGINPreprocessor 初始化于 {datetime.now()}\n")
            f.write(f"车辆数据文件: {self.vehicle_data_path}\n")
            f.write(f"输出目录: {self.output_dir}\n")
            f.write(f"地面基站数量: {self.num_ground_stations}\n")
            f.write(f"卫星数量: {self.num_satellites}\n")
            f.write(f"聚类方法: {self.cluster_method}\n")
            f.write("-" * 50 + "\n")
        
        # 增加高级分析参数
        self.vehicle_density_map = None
        self.traffic_hotspots = None
        self.coverage_radius = 1000  # 默认基站覆盖半径(米)
        self.satellite_altitude = 500000  # 卫星高度(米)
        self.connectivity_matrix = None
        self.vehicle_statistics = {}
    
    def log(self, message):
        """记录日志"""
        print(message)
        with open(self.log_file, 'a') as f:
            f.write(f"{datetime.now()}: {message}\n")
    
    def load_vehicle_data(self):
        """加载车辆数据"""
        self.log(f"开始加载车辆数据: {self.vehicle_data_path}...")
        
        # 检查文件是否存在
        if not os.path.exists(self.vehicle_data_path):
            self.log(f"错误: 车辆数据文件未找到 - {self.vehicle_data_path}")
            return False
            
        try:
            # 读取CSV文件
            self.vehicle_data = pd.read_csv(self.vehicle_data_path)
            self.log(f"成功加载车辆数据，共 {len(self.vehicle_data)} 行")
            
            # 获取唯一的车辆ID列表
            if 'vehicle_id' in self.vehicle_data.columns:
                self.vehicle_ids = self.vehicle_data['vehicle_id'].unique()
                self.log(f"识别出 {len(self.vehicle_ids)} 辆不同的车辆")
            
            # 按车辆ID分组，并提取轨迹
            if 'vehicle_id' in self.vehicle_data.columns and all(col in self.vehicle_data.columns for col in ['x', 'y']):
                for vehicle_id in self.vehicle_ids:
                    vehicle_df = self.vehicle_data[self.vehicle_data['vehicle_id'] == vehicle_id]
                    
                    # 提取轨迹数据
                    trajectory = vehicle_df[['x', 'y', 'z']].values if 'z' in vehicle_df.columns else \
                                 vehicle_df[['x', 'y']].values
                    
                    # 如果轨迹是2D的，添加z=0使其成为3D
                    if trajectory.shape[1] == 2:
                        trajectory = np.column_stack((trajectory, np.zeros(len(trajectory))))
                    
                    self.vehicle_trajectories.append(trajectory)
            else:
                # 如果没有vehicle_id列，我们尝试将整个数据集作为一个轨迹处理
                if all(col in self.vehicle_data.columns for col in ['x', 'y']):
                    trajectory = self.vehicle_data[['x', 'y']].values
                    
                    # 如果有z列，添加它
                    if 'z' in self.vehicle_data.columns:
                        trajectory = self.vehicle_data[['x', 'y', 'z']].values
                    else:
                        # 添加z=0
                        trajectory = np.column_stack((trajectory, np.zeros(len(trajectory))))
                    
                    self.vehicle_trajectories.append(trajectory)
                else:
                    self.log("警告: 数据中没有找到x和y坐标列")
            
            self.log(f"成功处理 {len(self.vehicle_trajectories)} 条车辆轨迹")
            return True
            
        except Exception as e:
            self.log(f"错误: 加载车辆数据失败 - {str(e)}")
            import traceback
            self.log(traceback.format_exc())
            return False
    
    def determine_ground_stations(self):
        """确定地面基站的最佳位置"""
        self.log(f"开始确定 {self.num_ground_stations} 个地面基站的位置...")
        
        if not self.vehicle_trajectories:
            self.log("错误: 未找到车辆轨迹数据，无法确定基站位置")
            return False
        
        try:
            # 将所有车辆轨迹点合并为一个数组
            all_points = np.vstack(self.vehicle_trajectories)
            
            # 仅使用x和y坐标进行聚类
            points_2d = all_points[:, :2]
            
            # 数据标准化
            scaler = StandardScaler()
            points_scaled = scaler.fit_transform(points_2d)
            
            # 使用K-means聚类确定基站位置
            kmeans = KMeans(n_clusters=self.num_ground_stations, random_state=42)
            kmeans.fit(points_scaled)
            
            # 获取聚类中心
            ground_centers_scaled = kmeans.cluster_centers_
            
            # 反标准化获取实际坐标
            ground_centers = scaler.inverse_transform(ground_centers_scaled)
            
            # 添加z坐标（假设地面高度为0）
            self.ground_stations = np.column_stack((ground_centers, np.zeros(len(ground_centers))))
            
            self.log(f"地面基站位置确定完成")
            
            # 将基站位置保存到文件 - 保存到positions文件夹
            ground_stations_file = os.path.join(self.position_dir, 'ground_stations.csv')
            pd.DataFrame(self.ground_stations, 
                         columns=['x', 'y', 'z']).to_csv(ground_stations_file, index=False)
            self.log(f"地面基站位置已保存到 {ground_stations_file}")
            
            return True
            
        except Exception as e:
            self.log(f"错误: 确定地面基站位置失败 - {str(e)}")
            return False
    
    def determine_satellite_positions(self):
        """确定卫星的最佳位置"""
        self.log(f"开始确定 {self.num_satellites} 颗卫星的位置...")
        
        try:
            # 这里使用简化模型，在较高高度上均匀分布卫星
            earth_radius = 6371000  # 地球半径(米)
            altitude = 750000  # 卫星高度(米)，低轨道卫星约750km
            
            # 计算卫星位置
            satellite_positions = []
            for i in range(self.num_satellites):
                # 在圆周上均匀分布
                angle = 2 * np.pi * i / self.num_satellites
                
                # 计算x, y坐标(在地球表面上的投影)
                x = (earth_radius + altitude) * np.cos(angle)
                y = (earth_radius + altitude) * np.sin(angle)
                
                # 高度为altitude
                z = altitude
                
                satellite_positions.append([x, y, z])
            
            self.satellites = np.array(satellite_positions)
            
            self.log(f"卫星位置确定完成")
            
            # 将卫星位置保存到文件 - 保存到positions文件夹
            satellites_file = os.path.join(self.position_dir, 'satellites.csv')
            pd.DataFrame(self.satellites, 
                         columns=['x', 'y', 'z']).to_csv(satellites_file, index=False)
            self.log(f"卫星位置已保存到 {satellites_file}")
            
            return True
            
        except Exception as e:
            self.log(f"错误: 确定卫星位置失败 - {str(e)}")
            return False
    
    def visualize_network_3d(self):
        """生成3D网络可视化图 - 分别保存地面视图和太空视图"""
        self.log("开始生成3D网络可视化...")
        
        try:
            # 1. 生成地面视图(车辆+基站)
            self.generate_ground_view()
            
            # 2. 生成太空视图(基站+卫星)
            self.generate_space_view()
            
            # 3. 生成卫星轨道视图
            self.visualize_satellite_orbits()
            
            self.log(f"3D网络可视化已保存到 {self.viz_dir} 目录")
            return True
            
        except Exception as e:
            self.log(f"错误: 生成3D网络可视化失败 - {str(e)}")
            import traceback
            self.log(traceback.format_exc())
            return False
            
    def generate_ground_view(self):
        """生成地面视图(车辆轨迹和基站)"""
        try:
            # 创建图形
            fig = plt.figure(figsize=(12, 10))
            ax = fig.add_subplot(111, projection='3d')
            
            # 获取车辆轨迹数据
            all_points = np.vstack(self.vehicle_trajectories)
            
            # 计算地面区域的边界
            x_min, x_max = np.min(all_points[:, 0]), np.max(all_points[:, 0])
            y_min, y_max = np.min(all_points[:, 1]), np.max(all_points[:, 1])
            z_min, z_max = 0, max(100, np.max(all_points[:, 2]) * 1.1)  # 确保地面视图有合适的高度
            
            # 绘制车辆轨迹（不同颜色表示不同车辆）
            sample_rate = max(1, len(self.vehicle_trajectories) // 10)  # 采样率，避免绘制过多轨迹
            colors = plt.cm.jet(np.linspace(0, 1, len(self.vehicle_trajectories[::sample_rate])))
            
            for i, trajectory in enumerate(self.vehicle_trajectories[::sample_rate]):
                if len(trajectory) > 0:
                    ax.plot(trajectory[:, 0], trajectory[:, 1], trajectory[:, 2], 
                            '-', linewidth=1.2, color=colors[i % len(colors)], alpha=0.7)
                    
                    # 标记起点和终点
                    ax.scatter(trajectory[0, 0], trajectory[0, 1], trajectory[0, 2], 
                               color=colors[i % len(colors)], s=30, marker='o')
                    ax.scatter(trajectory[-1, 0], trajectory[-1, 1], trajectory[-1, 2], 
                               color=colors[i % len(colors)], s=30, marker='x')
            
            # 绘制地面基站
            if self.ground_stations is not None:
                ax.scatter(self.ground_stations[:, 0], self.ground_stations[:, 1], self.ground_stations[:, 2],
                           s=200, c='red', marker='^', label='地面基站', alpha=0.8, edgecolor='black')
                
                # 为每个基站添加编号
                for i, station in enumerate(self.ground_stations):
                    ax.text(station[0], station[1], station[2] + 10, f'{i+1}', 
                            fontsize=10, ha='center', va='bottom', color='black')
            
            # 设置地面视图的标签和标题
            ax.set_xlabel('X 坐标 (米)', fontproperties=self.chinese_font)
            ax.set_ylabel('Y 坐标 (米)', fontproperties=self.chinese_font)
            ax.set_zlabel('Z 坐标 (米)', fontproperties=self.chinese_font)
            ax.set_title('地面视图 - 车辆轨迹和基站分布', fontproperties=self.chinese_font)
            
            # 设置地面视图的显示范围
            ax.set_xlim(x_min, x_max)
            ax.set_ylim(y_min, y_max)
            ax.set_zlim(z_min, z_max)
            
            # 添加地面平面网格
            xx, yy = np.meshgrid(np.linspace(x_min, x_max, 2), np.linspace(y_min, y_max, 2))
            zz = np.zeros(xx.shape)
            ax.plot_surface(xx, yy, zz, alpha=0.1, color='gray')
            
            ax.legend(prop=self.chinese_font)
            
            # 调整视角
            ax.view_init(elev=30, azim=45)
            
            # 保存地面视图
            ground_view_file = os.path.join(self.viz_dir, 'ground_view.png')
            plt.savefig(ground_view_file, dpi=300, bbox_inches='tight')
            plt.close()
            
            self.log(f"地面视图已保存到 {ground_view_file}")
            return True
        except Exception as e:
            self.log(f"错误: 生成地面视图失败 - {str(e)}")
            return False
            
    def generate_space_view(self):
        """生成太空视图(基站和卫星)"""
        try:
            fig = plt.figure(figsize=(12, 10))
            ax = fig.add_subplot(111, projection='3d')
            
            if self.satellites is not None and self.ground_stations is not None:
                # 绘制基站，使用较小的标记（因为这是太空视角）
                ax.scatter(self.ground_stations[:, 0], self.ground_stations[:, 1], self.ground_stations[:, 2],
                           s=100, c='red', marker='^', label='地面基站', alpha=0.8)
                
                # 绘制卫星
                ax.scatter(self.satellites[:, 0], self.satellites[:, 1], self.satellites[:, 2], 
                           s=200, c='green', marker='*', label='卫星', alpha=1)
                
                # 为卫星添加编号
                for i, satellite in enumerate(self.satellites):
                    ax.text(satellite[0], satellite[1], satellite[2], f'{i+1}', 
                            fontsize=10, ha='center', va='bottom', color='green')
                
                # 绘制卫星之间的连接线
                for i in range(len(self.satellites)):
                    next_i = (i + 1) % len(self.satellites)
                    ax.plot([self.satellites[i, 0], self.satellites[next_i, 0]], 
                            [self.satellites[i, 1], self.satellites[next_i, 1]],
                            [self.satellites[i, 2], self.satellites[next_i, 2]],
                            'g-', alpha=0.5, linewidth=1.5)
                
                # 绘制从基站到卫星的连接线（选择性地画出部分线，避免图形过于复杂）
                for i, station in enumerate(self.ground_stations):
                    if i % 3 == 0:  # 只为部分基站绘制连接线
                        sat_idx = i % len(self.satellites)
                        ax.plot([station[0], self.satellites[sat_idx, 0]], 
                                [station[1], self.satellites[sat_idx, 1]],
                                [station[2], self.satellites[sat_idx, 2]],
                                'b--', alpha=0.3)
            
            # 设置太空视图的标签和标题
            ax.set_xlabel('X 坐标 (米)', fontproperties=self.chinese_font)
            ax.set_ylabel('Y 坐标 (米)', fontproperties=self.chinese_font)
            ax.set_zlabel('Z 坐标 (米)', fontproperties=self.chinese_font)
            ax.set_title('太空视图 - 基站和卫星分布', fontproperties=self.chinese_font)
            
            # 确保太空视图有适当的比例
            ax.set_box_aspect([1, 1, 0.7])
            ax.view_init(elev=20, azim=30)
            
            # 添加图例
            ax.legend(prop=self.chinese_font)
            
            # 保存太空视图
            space_view_file = os.path.join(self.viz_dir, 'space_view.png')
            plt.savefig(space_view_file, dpi=300, bbox_inches='tight')
            plt.close()
            
            self.log(f"太空视图已保存到 {space_view_file}")
            return True
        except Exception as e:
            self.log(f"错误: 生成太空视图失败 - {str(e)}")
            return False

    def visualize_satellite_orbits(self):
        """单独生成卫星轨道的可视化图"""
        try:
            fig = plt.figure(figsize=(10, 8))
            ax = fig.add_subplot(111, projection='3d')
            
            # 绘制地球（简化为球体）
            earth_radius = 6371000  # 地球半径(米)
            u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j]
            x = earth_radius * np.cos(u) * np.sin(v) * 0.0001  # 缩小比例以便显示
            y = earth_radius * np.sin(u) * np.sin(v) * 0.0001
            z = earth_radius * np.cos(v) * 0.0001
            ax.plot_surface(x, y, z, color='blue', alpha=0.2)
            
            # 绘制卫星
            if self.satellites is not None:
                # 缩小比例以便显示
                scale = 0.0001  # 适当调整比例
                satellites_scaled = self.satellites * scale
                
                # 绘制卫星轨道平面
                orbit_radius = np.mean(np.sqrt(satellites_scaled[:, 0]**2 + satellites_scaled[:, 1]**2))
                theta = np.linspace(0, 2*np.pi, 100)
                x_orbit = orbit_radius * np.cos(theta)
                y_orbit = orbit_radius * np.sin(theta)
                z_orbit = np.zeros_like(theta)
                ax.plot(x_orbit, y_orbit, z_orbit, 'g--', alpha=0.5)
                
                # 绘制卫星
                ax.scatter(satellites_scaled[:, 0], satellites_scaled[:, 1], satellites_scaled[:, 2], 
                           s=100, c='green', marker='*', label='卫星')
                
                # 为卫星添加编号
                for i, satellite in enumerate(satellites_scaled):
                    ax.text(satellite[0], satellite[1], satellite[2], f'{i+1}', 
                            fontsize=9, ha='center', va='bottom', color='green')
                
                # 连接卫星
                for i in range(len(satellites_scaled)):
                    next_i = (i + 1) % len(satellites_scaled)
                    ax.plot([satellites_scaled[i, 0], satellites_scaled[next_i, 0]], 
                            [satellites_scaled[i, 1], satellites_scaled[next_i, 1]],
                            [satellites_scaled[i, 2], satellites_scaled[next_i, 2]],
                            'g-', alpha=0.7)
            
            # 设置标签
            ax.set_xlabel('X (km×10⁴)', fontproperties=self.chinese_font)
            ax.set_ylabel('Y (km×10⁴)', fontproperties=self.chinese_font)
            ax.set_zlabel('Z (km×10⁴)', fontproperties=self.chinese_font)
            ax.set_title('卫星轨道视图', fontproperties=self.chinese_font)
            
            # 保存图形到visualizations文件夹
            orbit_visualization_file = os.path.join(self.viz_dir, 'satellite_orbits.png')
            plt.savefig(orbit_visualization_file, dpi=300, bbox_inches='tight')
            plt.close()
            
            self.log(f"卫星轨道视图已保存到 {orbit_visualization_file}")
            return True
        except Exception as e:
            self.log(f"错误: 生成卫星轨道可视化失败 - {str(e)}")
            return False
    
    def create_coverage_analysis(self):
        """创建覆盖范围分析"""
        self.log("开始生成覆盖范围分析...")
        
        try:
            # 确定分析区域范围
            x_min, y_min = float('inf'), float('inf')
            x_max, y_max = float('-inf'), float('-inf')
            
            for trajectory in self.vehicle_trajectories:
                x_min = min(x_min, np.min(trajectory[:, 0]))
                y_min = min(y_min, np.min(trajectory[:, 1]))
                x_max = max(x_max, np.max(trajectory[:, 0]))
                y_max = max(y_max, np.max(trajectory[:, 1]))
            
            # 创建网格
            grid_size = 100
            x = np.linspace(x_min, x_max, grid_size)
            y = np.linspace(y_min, y_max, grid_size)
            X, Y = np.meshgrid(x, y)
            
            # 初始化覆盖度矩阵
            coverage = np.zeros((grid_size, grid_size))
            
            # 假设地面基站的覆盖半径
            ground_station_radius = 1000  # 米
            
            # 计算每个网格点被覆盖的程度
            for i in range(grid_size):
                for j in range(grid_size):
                    point = np.array([X[i, j], Y[i, j]])
                    
                    # 计算到最近地面基站的距离
                    if self.ground_stations is not None:
                        min_distance = float('inf')
                        for station in self.ground_stations:
                            dist = np.sqrt((point[0] - station[0])**2 + (point[1] - station[1])**2)
                            if dist < min_distance:
                                min_distance = dist
                        
                        # 距离越近，覆盖度越高
                        if min_distance < ground_station_radius:
                            coverage[i, j] = 1 - min_distance/ground_station_radius
            
            # 绘制热力图
            plt.figure(figsize=(12, 10))
            plt.pcolormesh(X, Y, coverage, cmap='jet', shading='auto')
            cbar = plt.colorbar(label='覆盖度')
            cbar.set_label('覆盖度', fontproperties=self.chinese_font)
            
            # 绘制地面基站位置
            if self.ground_stations is not None:
                plt.scatter(self.ground_stations[:, 0], self.ground_stations[:, 1], 
                           s=100, c='red', marker='^', label='地面基站')
            
            # 设置轴标签和标题 - 使用中文字体
            plt.xlabel('X 坐标 (米)', fontproperties=self.chinese_font)
            plt.ylabel('Y 坐标 (米)', fontproperties=self.chinese_font)
            plt.title('地面基站覆盖范围分析', fontproperties=self.chinese_font)
            plt.legend(prop=self.chinese_font)
            
            # 保存图形到analysis文件夹
            coverage_file = os.path.join(self.analysis_dir, 'coverage_analysis.png')
            plt.savefig(coverage_file, dpi=300, bbox_inches='tight')
            plt.close()
            
            self.log(f"覆盖范围分析已保存到 {coverage_file}")
            return True
            
        except Exception as e:
            self.log(f"错误: 生成覆盖范围分析失败 - {str(e)}")
            return False
    
    def analyze_vehicle_density(self, grid_size=100):
        """分析车辆密度分布"""
        self.log("分析车辆密度分布...")
        
        if not self.vehicle_trajectories:
            self.log("错误：没有车辆轨迹数据可供分析")
            return False
        
        try:
            # 确定区域范围
            x_min, y_min = float('inf'), float('inf')
            x_max, y_max = float('-inf'), float('-inf')
            
            for trajectory in self.vehicle_trajectories:
                if len(trajectory) > 0:
                    x_min = min(x_min, np.min(trajectory[:, 0]))
                    y_min = min(y_min, np.min(trajectory[:, 1]))
                    x_max = max(x_max, np.max(trajectory[:, 0]))
                    y_max = max(y_max, np.max(trajectory[:, 1]))
            
            # 创建密度网格
            x_edges = np.linspace(x_min, x_max, grid_size+1)
            y_edges = np.linspace(y_min, y_max, grid_size+1)
            density_map = np.zeros((grid_size, grid_size))
            
            # 统计每个网格中的车辆点数
            for trajectory in self.vehicle_trajectories:
                if len(trajectory) > 0:
                    x_indices = np.digitize(trajectory[:, 0], x_edges) - 1
                    y_indices = np.digitize(trajectory[:, 1], y_edges) - 1
                    
                    # 确保索引在有效范围内
                    x_indices = np.clip(x_indices, 0, grid_size-1)
                    y_indices = np.clip(y_indices, 0, grid_size-1)
                    
                    for x_idx, y_idx in zip(x_indices, y_indices):
                        density_map[y_idx, x_idx] += 1
            
            self.vehicle_density_map = {
                'map': density_map,
                'x_edges': x_edges,
                'y_edges': y_edges
            }
            
            # 生成热点图
            plt.figure(figsize=(12, 10))
            plt.pcolormesh(x_edges, y_edges, density_map, cmap='jet', shading='auto')
            cbar = plt.colorbar(label='车辆轨迹点密度')
            cbar.set_label('车辆轨迹点密度', fontproperties=self.chinese_font)
            
            plt.xlabel('X 坐标 (米)', fontproperties=self.chinese_font)
            plt.ylabel('Y 坐标 (米)', fontproperties=self.chinese_font)
            plt.title('车辆密度分布热力图', fontproperties=self.chinese_font)
            
            # 保存图形到analysis文件夹
            density_map_file = os.path.join(self.analysis_dir, 'vehicle_density_map.png')
            plt.savefig(density_map_file, dpi=300, bbox_inches='tight')
            plt.close()
            
            self.log(f"车辆密度分析已保存到 {density_map_file}")
            
            # 识别交通热点（密度最高的区域）
            flat_indices = np.argsort(density_map.flatten())[-10:]  # 取密度最高的10个区域
            hotspot_indices = np.unravel_index(flat_indices, density_map.shape)
            
            hotspots = []
            for y_idx, x_idx in zip(hotspot_indices[0], hotspot_indices[1]):
                x_center = (x_edges[x_idx] + x_edges[x_idx + 1]) / 2
                y_center = (y_edges[y_idx] + y_edges[y_idx + 1]) / 2
                density = density_map[y_idx, x_idx]
                hotspots.append({
                    'x': x_center,
                    'y': y_center,
                    'density': density
                })
            
            self.traffic_hotspots = hotspots
            
            # 保存热点数据到data文件夹
            hotspots_file = os.path.join(self.data_dir, 'traffic_hotspots.json')
            with open(hotspots_file, 'w') as f:
                json.dump(hotspots, f, indent=2)
            
            self.log(f"交通热点数据已保存到 {hotspots_file}")
            
            return True
            
        except Exception as e:
            self.log(f"错误: 分析车辆密度失败 - {str(e)}")
            return False
    
    def calculate_optimal_stations(self):
        """计算指定数量的基站位置 - 直接使用K-means生成指定数量的基站"""
        self.log(f"计算 {self.num_ground_stations} 个基站的最佳位置...")
        
        if not self.vehicle_trajectories:
            self.log("错误：没有车辆轨迹数据可供分析")
            return False
        
        try:
            # 将所有车辆轨迹点合并
            all_points = np.vstack([traj[:, :2] for traj in self.vehicle_trajectories if len(traj) > 0])
            
            # 使用K-means直接生成指定数量的基站
            kmeans = KMeans(n_clusters=self.num_ground_stations, random_state=42)
            kmeans.fit(all_points)
            centers = kmeans.cluster_centers_
            
            # 添加z=0的垂直坐标（地面高度）
            self.ground_stations = np.column_stack((centers, np.zeros(len(centers))))
            
            self.log(f"已生成 {len(self.ground_stations)} 个地面基站位置")
            
            # 将基站位置保存到文件 - 保存到positions文件夹
            ground_stations_file = os.path.join(self.position_dir, 'ground_stations.csv')
            pd.DataFrame(self.ground_stations, columns=['x', 'y', 'z']).to_csv(ground_stations_file, index=False)
            self.log(f"基站位置已保存到 {ground_stations_file}")
            
            return True
        except Exception as e:
            self.log(f"错误: 计算基站位置失败 - {str(e)}")
            import traceback
            self.log(traceback.format_exc())
            return False
    
    def optimize_satellite_constellation(self):
        """配置卫星位置 - 直接生成指定数量的卫星"""
        self.log(f"配置 {self.num_satellites} 颗卫星的位置...")
        
        try:
            earth_radius = 6371000  # 地球半径(米)
            altitude = 750000  # 卫星高度750km
            
            # 计算卫星位置 - 围绕地球均匀分布
            satellite_positions = []
            for i in range(self.num_satellites):
                # 均匀分布在一个圆上
                angle = 2 * np.pi * i / self.num_satellites
                
                # 计算坐标
                x = (earth_radius + altitude) * np.cos(angle)
                y = (earth_radius + altitude) * np.sin(angle)
                z = altitude  # 所有卫星在同一高度
                
                satellite_positions.append([x, y, z])
            
            self.satellites = np.array(satellite_positions)
            
            # 保存卫星位置到positions文件夹
            satellites_file = os.path.join(self.position_dir, 'satellites.csv')
            pd.DataFrame(self.satellites, columns=['x', 'y', 'z']).to_csv(satellites_file, index=False)
            self.log(f"卫星位置已保存到 {satellites_file}")
            
            self.log(f"已配置 {len(self.satellites)} 颗卫星，高度为 {altitude/1000} km")
            return True
        except Exception as e:
            self.log(f"错误: 配置卫星位置失败 - {str(e)}")
            return False
    
    def analyze_vehicle_statistics(self):
        """分析车辆统计信息"""
        self.log("分析车辆统计信息...")
        
        try:
            if self.vehicle_data is None:
                self.log("警告: 没有车辆数据可供分析")
                return False
            
            # 收集统计数据
            stats = {
                'total_data_points': len(self.vehicle_data),
                'total_vehicles': len(self.vehicle_ids) if hasattr(self, 'vehicle_ids') and len(self.vehicle_ids) > 0 else 1,
                'trajectory_lengths': [len(traj) for traj in self.vehicle_trajectories],
                'speed_statistics': {
                    'min': float('inf'),
                    'max': 0,
                    'avg': 0
                },
                'total_distance': 0,
                'time_periods': {}
            }
            
            # 如果有速度数据，计算速度统计
            if 'speed' in self.vehicle_data.columns:
                speed_data = self.vehicle_data['speed'].dropna()
                if len(speed_data) > 0:
                    stats['speed_statistics']['min'] = float(speed_data.min())
                    stats['speed_statistics']['max'] = float(speed_data.max())
                    stats['speed_statistics']['avg'] = float(speed_data.mean())
            
            # 如果有时间数据，分析时间分布
            if 'time' in self.vehicle_data.columns:
                time_data = self.vehicle_data['time'].dropna()
                if len(time_data) > 0:
                    # 将时间分成小时段
                    for time_val in time_data:
                        try:
                            hour = int(float(time_val) / 3600)  # 假设时间单位是秒
                            hour_str = f"{hour:02d}:00-{(hour+1):02d}:00"
                            if hour_str not in stats['time_periods']:
                                stats['time_periods'][hour_str] = 0
                            stats['time_periods'][hour_str] += 1
                        except (ValueError, TypeError):
                            pass
            
            # 计算总行驶距离
            total_distance = 0
            for traj in self.vehicle_trajectories:
                if len(traj) > 1:
                    # 计算连续点之间的欧氏距离并求和
                    distances = np.sqrt(np.sum(np.diff(traj[:, :2], axis=0)**2, axis=1))
                    total_distance += np.sum(distances)
            
            stats['total_distance'] = float(total_distance)
            
            # 计算轨迹长度的统计信息
            if stats['trajectory_lengths']:
                stats['trajectory_length_stats'] = {
                    'min': min(stats['trajectory_lengths']),
                    'max': max(stats['trajectory_lengths']),
                    'avg': sum(stats['trajectory_lengths']) / len(stats['trajectory_lengths']),
                    'median': float(np.median(stats['trajectory_lengths']))
                }
            
            self.vehicle_statistics = stats
            
            # 保存统计数据到data文件夹
            stats_file = os.path.join(self.data_dir, 'vehicle_statistics.json')
            with open(stats_file, 'w') as f:
                # 转换numpy类型为Python原生类型
                stats_serializable = json.loads(
                    json.dumps(stats, default=lambda obj: float(obj) if isinstance(obj, np.number) else obj)
                )
                json.dump(stats_serializable, f, indent=2)
            
            # 绘制统计图表
            self.visualize_statistics(stats)
            
            self.log("车辆统计分析完成")
            return True
            
        except Exception as e:
            self.log(f"错误: 分析车辆统计信息失败 - {str(e)}")
            import traceback
            self.log(traceback.format_exc())
            return False
    
    def visualize_statistics(self, stats):
        """可视化统计信息"""
        try:
            # 绘制轨迹长度分布直方图
            plt.figure(figsize=(10, 6))
            plt.hist(stats['trajectory_lengths'], bins=30, alpha=0.7, color='blue')
            plt.axvline(stats['trajectory_length_stats']['avg'], color='red', linestyle='dashed', linewidth=1, 
                      label=f"平均长度: {stats['trajectory_length_stats']['avg']:.1f}")
            plt.axvline(stats['trajectory_length_stats']['median'], color='green', linestyle='dashed', linewidth=1, 
                      label=f"中位长度: {stats['trajectory_length_stats']['median']:.1f}")
            plt.xlabel('轨迹点数', fontproperties=self.chinese_font)
            plt.ylabel('车辆数', fontproperties=self.chinese_font)
            plt.title('车辆轨迹长度分布', fontproperties=self.chinese_font)
            plt.legend(prop=self.chinese_font)
            plt.grid(True, alpha=0.3)
            
            # 保存轨迹长度分布到analysis文件夹
            trajectory_dist_file = os.path.join(self.analysis_dir, 'trajectory_length_distribution.png')
            plt.savefig(trajectory_dist_file, dpi=300, bbox_inches='tight')
            plt.close()
            
            # 绘制时间段分布图(如果有数据)
            if stats['time_periods']:
                # 排序时间段
                sorted_periods = sorted(stats['time_periods'].items(), key=lambda x: int(x[0].split(':')[0]))
                periods = [p[0] for p in sorted_periods]
                counts = [p[1] for p in sorted_periods]
                
                plt.figure(figsize=(12, 6))
                plt.bar(periods, counts, color='skyblue')
                plt.xlabel('时间段', fontproperties=self.chinese_font)
                plt.ylabel('数据点数', fontproperties=self.chinese_font)
                plt.title('车辆数据时间分布', fontproperties=self.chinese_font)
                plt.xticks(rotation=45)
                plt.tight_layout()
                plt.grid(True, alpha=0.3)
                
                # 保存时间分布图到analysis文件夹
                time_dist_file = os.path.join(self.analysis_dir, 'time_distribution.png')
                plt.savefig(time_dist_file, dpi=300, bbox_inches='tight')
                plt.close()
            
            # 创建综合统计信息图
            plt.figure(figsize=(10, 8))
            plt.text(0.5, 0.95, "车辆数据统计摘要", ha='center', va='top', fontsize=16, weight='bold', 
                  fontproperties=self.chinese_font)
            plt.text(0.05, 0.85, f"总计车辆数: {stats['total_vehicles']}", fontsize=12, 
                  fontproperties=self.chinese_font)
            plt.text(0.05, 0.80, f"平均轨迹长度: {stats['trajectory_length_stats']['avg']:.1f} 点", fontsize=12, 
                  fontproperties=self.chinese_font)
            plt.text(0.05, 0.75, f"最长轨迹: {stats['trajectory_length_stats']['max']} 点", fontsize=12, 
                  fontproperties=self.chinese_font)
            plt.text(0.05, 0.70, f"最短轨迹: {stats['trajectory_length_stats']['min']} 点", fontsize=12, 
                  fontproperties=self.chinese_font)
            
            if stats['speed_statistics']['max'] > 0:
                plt.text(0.05, 0.60, f"平均速度: {stats['speed_statistics']['avg']:.2f} m/s", fontsize=12, 
                      fontproperties=self.chinese_font)
                plt.text(0.05, 0.55, f"最高速度: {stats['speed_statistics']['max']:.2f} m/s", fontsize=12, 
                      fontproperties=self.chinese_font)
                plt.text(0.05, 0.50, f"最低速度: {stats['speed_statistics']['min']:.2f} m/s", fontsize=12, 
                      fontproperties=self.chinese_font)
            
            plt.text(0.05, 0.40, f"总行驶距离: {stats['total_distance']/1000:.2f} km", fontsize=12, 
                  fontproperties=self.chinese_font)
            
            plt.axis('off')  # 不显示坐标轴
            
            # 保存统计摘要到visualizations文件夹
            summary_file = os.path.join(self.viz_dir, 'statistics_summary.png')
            plt.savefig(summary_file, dpi=300, bbox_inches='tight')
            plt.close()
            
        except Exception as e:
            self.log(f"错误: 可视化统计数据失败 - {str(e)}")
    
    def calculate_network_connectivity(self):
        """计算网络连接性"""
        self.log("计算网络连接性...")
        
        try:
            if self.ground_stations is None or self.satellites is None:
                self.log("错误: 需要先确定基站和卫星位置")
                return False
                
            # 简化的连接性模型
            # 1. 地面车辆可以连接到一定范围内的基站
            # 2. 基站可以连接到上空的卫星
            # 3. 卫星之间可以相互连接形成星间链路
            
            # 计算车辆到基站的连接性
            # 修正：使用vehicle_trajectories而不是vehicle_data，因为vehicle_data可能是Series
            vehicle_count = len(self.vehicle_trajectories)
            vehicle_station_connectivity = np.zeros((vehicle_count, len(self.ground_stations)))
            
            for i, trajectory in enumerate(self.vehicle_trajectories):
                if len(trajectory) > 0:
                    # 使用最后一个位置点评估连接性
                    last_pos = trajectory[-1, :2]  # 只取x,y坐标
                    
                    for j, station in enumerate(self.ground_stations):
                        # 计算距离
                        distance = np.sqrt(np.sum((last_pos - station[:2])**2))
                        
                        # 如果在覆盖范围内，标记为连接
                        if distance <= self.coverage_radius:
                            vehicle_station_connectivity[i, j] = 1
            
            # 计算基站到卫星的连接性(简化模型，假设每个基站可连接到视野范围内的卫星)
            station_satellite_connectivity = np.ones((len(self.ground_stations), len(self.satellites)))
            
            # 计算卫星间连接性(简化模型，假设相邻卫星可以连接)
            satellite_connectivity = np.zeros((len(self.satellites), len(self.satellites)))
            for i in range(len(self.satellites)):
                # 连接到相邻的两颗卫星(环形拓扑)
                next_idx = (i + 1) % len(self.satellites)
                prev_idx = (i - 1) % len(self.satellites)
                satellite_connectivity[i, next_idx] = 1
                satellite_connectivity[i, prev_idx] = 1
            
            # 保存连接性矩阵到data文件夹
            np.save(os.path.join(self.data_dir, 'vehicle_station_connectivity.npy'), vehicle_station_connectivity)
            np.save(os.path.join(self.data_dir, 'station_satellite_connectivity.npy'), station_satellite_connectivity)
            np.save(os.path.join(self.data_dir, 'satellite_connectivity.npy'), satellite_connectivity)
            
            # 分析整体连接性
            vehicles_connected = np.sum(np.any(vehicle_station_connectivity, axis=1))
            connectivity_rate = vehicles_connected / vehicle_count if vehicle_count > 0 else 0
            
            connectivity_analysis = {
                'vehicles_total': vehicle_count,
                'vehicles_connected': int(vehicles_connected),
                'connectivity_rate': float(connectivity_rate),
                'average_stations_per_vehicle': float(np.mean(np.sum(vehicle_station_connectivity, axis=1))),
                'average_vehicles_per_station': float(np.mean(np.sum(vehicle_station_connectivity, axis=0))),
                'satellite_links': int(np.sum(satellite_connectivity) // 2)  # 除以2避免双重计数
            }
            
            # 保存连接性分析到data文件夹
            connectivity_file = os.path.join(self.data_dir, 'connectivity_analysis.json')
            with open(connectivity_file, 'w') as f:
                json.dump(connectivity_analysis, f, indent=2)
            
            self.log(f"网络连接性分析完成: {connectivity_rate*100:.1f}% 的车辆可以连接到基站")
            
            # 可视化连接性
            self.visualize_connectivity(vehicle_station_connectivity, connectivity_analysis)
            
            return True
            
        except Exception as e:
            self.log(f"错误: 计算网络连接性失败 - {str(e)}")
            import traceback
            self.log(traceback.format_exc())
            return False
    
    def visualize_connectivity(self, vehicle_station_connectivity, analysis):
        """可视化网络连接性"""
        try:
            # 创建连接性饼图
            plt.figure(figsize=(10, 8))
            connected = analysis['vehicles_connected']
            not_connected = analysis['vehicles_total'] - connected
            
            plt.pie(
                [connected, not_connected], 
                labels=['已连接', '未连接'], 
                autopct='%1.1f%%',
                colors=['#66b3ff', '#ff9999'],
                startangle=90,
                textprops={'fontproperties': self.chinese_font}
            )
            plt.title('车辆网络连接率', fontproperties=self.chinese_font)
            plt.axis('equal')  # 确保饼图是圆形的
            
            # 保存连接率饼图到analysis文件夹
            pie_file = os.path.join(self.analysis_dir, 'connectivity_pie.png')
            plt.savefig(pie_file, dpi=300, bbox_inches='tight')
            plt.close()
            
            # 创建基站负载分布图
            station_loads = np.sum(vehicle_station_connectivity, axis=0)
            
            plt.figure(figsize=(12, 6))
            plt.bar(range(1, len(station_loads)+1), station_loads, color='skyblue')
            plt.xlabel('基站ID', fontproperties=self.chinese_font)
            plt.ylabel('连接的车辆数', fontproperties=self.chinese_font)
            plt.title('基站负载分布', fontproperties=self.chinese_font)
            plt.grid(True, alpha=0.3)
            
            # 保存基站负载分布到analysis文件夹
            load_file = os.path.join(self.analysis_dir, 'station_load.png')
            plt.savefig(load_file, dpi=300, bbox_inches='tight')
            plt.close()
            
            # 创建连接性热图
            if vehicle_station_connectivity.shape[0] <= 100:  # 如果车辆数不太多
                plt.figure(figsize=(12, 10))
                plt.imshow(vehicle_station_connectivity, aspect='auto', cmap='Blues')
                cbar = plt.colorbar()
                cbar.set_label('连接状态', fontproperties=self.chinese_font)
                plt.xlabel('基站ID', fontproperties=self.chinese_font)
                plt.ylabel('车辆ID', fontproperties=self.chinese_font)
                plt.title('车辆-基站连接热图', fontproperties=self.chinese_font)
                
                # 保存连接性热图到analysis文件夹
                heatmap_file = os.path.join(self.analysis_dir, 'connectivity_heatmap.png')
                plt.savefig(heatmap_file, dpi=300, bbox_inches='tight')
                plt.close()
        
        except Exception as e:
            self.log(f"错误: 可视化连接性数据失败 - {str(e)}")
    
    def process(self):
        """执行完整的处理流程"""
        self.log("开始完整处理流程...")
        
        # 加载车辆数据
        if not self.load_vehicle_data():
            self.log("错误: 加载车辆数据失败，处理终止")
            return False
        
        # 分析车辆密度分布
        self.analyze_vehicle_density()
        
        # 计算基站位置 - 直接使用指定数量
        self.calculate_optimal_stations()
        
        # 配置卫星位置 - 直接使用指定数量
        self.optimize_satellite_constellation()
        
        # 生成3D可视化 (改进版)
        self.visualize_network_3d()
        
        # 创建覆盖范围分析
        self.create_coverage_analysis()
        
        # 分析车辆统计信息
        self.analyze_vehicle_statistics()
        
        # 计算网络连接性
        self.calculate_network_connectivity()
        
        # 生成结果索引文件
        self.generate_result_index()
        
        self.log("处理流程完成！")
        
        # 最终确认文件已生成
        self.log(f"基站位置文件: {os.path.join(self.position_dir, 'ground_stations.csv')}")
        self.log(f"卫星位置文件: {os.path.join(self.position_dir, 'satellites.csv')}")
        
        return True
        
    def generate_result_index(self):
        """生成结果索引HTML文件"""
        try:
            # 创建一个简单的HTML索引文件，列出所有生成的结果文件
            html_content = """
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="utf-8">
                <title>SAGIN车辆数据分析结果</title>
                <style>
                    body { font-family: Arial, sans-serif; margin: 20px; }
                    h1, h2 { color: #333; }
                    .section { margin-bottom: 30px; }
                    .file-list { margin-left: 20px; }
                    .file-item { margin-bottom: 8px; }
                    img { max-width: 300px; border: 1px solid #ddd; margin: 5px; }
                    .thumbnail-container { display: flex; flex-wrap: wrap; }
                </style>
            </head>
            <body>
                <h1>SAGIN车辆数据分析结果</h1>
                <p>生成时间: {datetime}</p>
                
                <div class="section">
                    <h2>可视化结果</h2>
                    <div class="thumbnail-container">
            """
            
            # 添加可视化图片
            viz_files = glob.glob(os.path.join(self.viz_dir, '*.png'))
            for viz_file in viz_files:
                filename = os.path.basename(viz_file)
                rel_path = os.path.join('visualizations', filename)
                html_content += f'<div class="file-item"><img src="{rel_path}" alt="{filename}"><br>{filename}</div>\n'
            
            html_content += """
                    </div>
                </div>
                
                <div class="section">
                    <h2>分析结果</h2>
                    <div class="thumbnail-container">
            """
            
            # 添加分析结果图片
            analysis_files = glob.glob(os.path.join(self.analysis_dir, '*.png'))
            for analysis_file in analysis_files:
                filename = os.path.basename(analysis_file)
                rel_path = os.path.join('analysis', filename)
                html_content += f'<div class="file-item"><img src="{rel_path}" alt="{filename}"><br>{filename}</div>\n'
            
            html_content += """
                    </div>
                </div>
                
                <div class="section">
                    <h2>位置数据</h2>
                    <div class="file-list">
            """
            
            # 添加位置数据文件
            position_files = glob.glob(os.path.join(self.position_dir, '*.*'))
            for position_file in position_files:
                filename = os.path.basename(position_file)
                html_content += f'<div class="file-item">{filename}</div>\n'
            
            html_content += """
                    </div>
                </div>
                
                <div class="section">
                    <h2>数据文件</h2>
                    <div class="file-list">
            """
            
            # 添加其他数据文件
            data_files = glob.glob(os.path.join(self.data_dir, '*.*'))
            for data_file in data_files:
                filename = os.path.basename(data_file)
                html_content += f'<div class="file-item">{filename}</div>\n'
            
            html_content += """
                    </div>
                </div>
            </body>
            </html>
            """
            
            # 填充动态内容
            html_content = html_content.format(
                datetime=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            )
            
            # 保存HTML文件
            index_file = os.path.join(self.output_dir, 'index.html')
            with open(index_file, 'w') as f:
                f.write(html_content)
            
            self.log(f"结果索引文件已生成: {index_file}")
            return True
        except Exception as e:
            self.log(f"警告: 生成结果索引失败 - {str(e)}")
            return False

def scan_csv_files(directory):
    """扫描指定目录及其子目录中的所有CSV文件"""
    csv_files = []
    
    if not os.path.exists(directory) or not os.path.isdir(directory):
        print(f"错误: 目录不存在 - {directory}")
        return csv_files
        
    for root, _, files in os.walk(directory):
        for file in files:
            if file.endswith('.csv'):
                file_path = os.path.join(root, file)
                csv_files.append(file_path)
    
    return csv_files


def interactive_input():
    """获取用户交互输入"""
    print("\n==== SAGIN车辆数据分析工具 ====\n")
    
    # 让用户输入数据文件夹路径
    while True:
        folder_path = input("请输入包含车辆数据的文件夹路径: ")
        
        # 如果输入为空，使用默认路径
        if not folder_path.strip():
            base_dir = os.path.dirname(os.path.dirname(os.path.dirname(current_dir)))
            folder_path = os.path.join(base_dir, 'sumo')
            print(f"使用默认路径: {folder_path}")
        
        # 扫描CSV文件
        csv_files = scan_csv_files(folder_path)
        
        if csv_files:
            break
        else:
            print(f"错误: 在 {folder_path} 及其子目录中未找到CSV文件")
            retry = input("是否重试? (y/n): ")
            if retry.lower() != 'y':
                return None, None, None, None
    
    # 显示找到的CSV文件
    print(f"\n找到 {len(csv_files)} 个CSV文件:")
    for i, file_path in enumerate(csv_files, 1):
        print(f"{i}. {file_path}")
    
    # 让用户选择CSV文件
    while True:
        file_choice = input("\n请选择车辆数据CSV文件 (输入编号): ")
        try:
            choice_idx = int(file_choice)
            if 1 <= choice_idx <= len(csv_files):
                vehicle_data_path = csv_files[choice_idx - 1]
                break
            else:
                print(f"请输入1到{len(csv_files)}之间的数字")
        except ValueError:
            print("请输入有效的数字")
    
    # 获取基站和卫星数量
    try:
        num_ground_stations = int(input("\n请输入地面基站数量 (默认: 10): ") or 10)
        num_satellites = int(input("请输入卫星数量 (默认: 5): ") or 5)
    except ValueError:
        print("输入无效，使用默认值")
        num_ground_stations = 10
        num_satellites = 5
    
    # 选择聚类方法
    print("\n可用的聚类方法:")
    print("1. K-means 聚类 (默认)")
    print("2. DBSCAN 聚类")
    
    cluster_method = 'kmeans'  # 默认方法
    method_choice = input("请选择聚类方法 (输入编号, 默认: 1): ")
    if method_choice == '2':
        cluster_method = 'dbscan'
    
    return vehicle_data_path, num_ground_stations, num_satellites, cluster_method


def parse_arguments():
    """解析命令行参数"""
    parser = argparse.ArgumentParser(description="SAGIN车辆数据预处理和基站优化")
    
    parser.add_argument('--csv-file', type=str, 
                        help='车辆数据CSV文件的完整路径')
    parser.add_argument('--output', type=str, 
                        help='输出目录路径')
    parser.add_argument('--ground-stations', type=int, default=10,
                        help='地面基站数量 (默认: 10)')
    parser.add_argument('--satellites', type=int, default=5,
                        help='卫星数量 (默认: 5)')
    parser.add_argument('--cluster-method', type=str, default='kmeans',
                        choices=['kmeans', 'dbscan', 'hierarchical'],
                        help='聚类方法 (默认: kmeans)')
    parser.add_argument('--coverage-radius', type=float, default=1000,
                        help='基站覆盖半径(米) (默认: 1000)')
    parser.add_argument('--interactive', action='store_true',
                        help='启用交互模式，忽略其他参数')
    
    return parser.parse_args()


def main():
    """主函数"""
    # 解析命令行参数
    args = parse_arguments()
    
    # 决定是否使用交互模式
    if args.interactive or args.csv_file is None:  
        vehicle_data_path, num_ground_stations, num_satellites, cluster_method = interactive_input()
        if vehicle_data_path is None:
            print("未能获取有效的输入，程序退出")
            return 1
    else:
        vehicle_data_path = args.csv_file
        num_ground_stations = args.ground_stations
        num_satellites = args.satellites
        cluster_method = args.cluster_method
    
    # 创建预处理器实例
    preprocessor = SAGINPreprocessor(
        vehicle_data_path=vehicle_data_path,
        output_dir=args.output,
        num_ground_stations=num_ground_stations,
        num_satellites=num_satellites,
        cluster_method=cluster_method
    )
    
    # 设置覆盖半径
    preprocessor.coverage_radius = args.coverage_radius
    
    # 执行处理
    success = preprocessor.process()
    
    if success:
        print(f"\n处理完成！输出结果保存在: {preprocessor.output_dir}")
    
    return 0 if success else 1


if __name__ == "__main__":
    sys.exit(main())
